package com.group9.handinhand.controller;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.group9.handinhand.controller.form.EventCreateForm;
import com.group9.handinhand.controller.form.EventUpdateForm;
import com.group9.handinhand.controller.form.EventViewForm;
import com.group9.handinhand.service.CommunityService;
import com.group9.handinhand.service.EventService;
import com.group9.handinhand.service.TagService;
import com.group9.handinhand.service.so.ActivityEnums.ActivityType;
import com.group9.handinhand.service.so.CommunityMemberSO;
import com.group9.handinhand.service.so.CommunitySO;
import com.group9.handinhand.service.so.EventAttenderSO;
import com.group9.handinhand.service.so.EventPostSO;
import com.group9.handinhand.service.so.EventSO;
import com.group9.handinhand.service.so.TagSO;
import com.group9.handinhand.service.so.UserSO;
import com.group9.handinhand.service.so.UserTagSO;

/**
 *  a class for event controller
 *
 */
@Controller
public class EventController extends AbstractBaseController {
	
	@Autowired
	CommunityService communityService;
	
	@Autowired
	EventService eventService;
	
	@Autowired
	private TagService tagService;
	
	private List<UserSO> moderatorsList;
	private UserSO creator;
	/**
	 * a controller for viewing the event list
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/events")
	public String events(HttpServletRequest request, Model model){
		
		UserSO user = getUser();
		if(user == null){
			return "redirect:";
		}
		
		List<EventSO> eventList = eventService.getEventsByUser(user);
		model.addAttribute("eventList", eventList);
		return "listEvents";
	}
	/**
	 * a controller for creating new event
	 * @param communityId
	 * @param eventCreateForm
	 * @param errors
	 * @param request
	 * @param model
	 * @return the newly created event page
	 */
	@RequestMapping(value = "/communities/{communityId}/newEvent")
	public String newEvent(@PathVariable Long communityId, EventCreateForm eventCreateForm, BindingResult errors, HttpServletRequest request, Model model){
		
		EventSO so = new EventSO();
		so.setCommunity(communityService.getCommunityById(communityId));
		
		if(eventCreateForm.getEvent() == null)
			eventCreateForm.setEvent(new EventSO());
		
		return "newEvent";
	}
	/**
	 * a controller for saving an event
	 * @param communityId
	 * @param eventCreateForm
	 * @param errors
	 * @param request
	 * @param model
	 * @return the event of that community
	 */
	@RequestMapping(value = "/communities/{communityId}/saveEvent")
	public String saveEvent(@PathVariable Long communityId, EventCreateForm eventCreateForm, BindingResult errors, HttpServletRequest request, Model model){
		
		validateNewEvent(eventCreateForm, errors);
		if(errors.hasErrors()){
			return newEvent(communityId, eventCreateForm, errors, request, model);
		}
		eventCreateForm.setStartAndEndDates();
		EventSO event = eventCreateForm.getEvent();
		
		event = eventService.saveEvent(event, getUser(), communityId);
		
		List<String> selectedTags = eventCreateForm.getSelectedTagsAsList();
		
		tagService.saveEventTags(event,selectedTags);
		
		return "redirect:/communities/" + communityId + "/events/" + event.getId();
	}
	/**
	 * a controller for viewing the event list of the community
	 * @param communityId
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events")
	public String listEventsOfCommunity(@PathVariable Long communityId, HttpServletRequest request, Model model){
		
		UserSO user = getUser();
		if(user == null){
			return "redirect:";
		}
		
		CommunitySO community = communityService.getCommunityById(communityId);
		
		Set<EventSO> eventList = community.getEvents();
		model.addAttribute("eventList", eventList);
		model.addAttribute("communityId", communityId);
		return "listEventsOfCommunity";
	}
	/**
	 * a controller for viewing a specific event
	 * @param communityId
	 * @param eventId
	 * @param eventViewForm
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events/{eventId}")
	public String viewEvent(@PathVariable Long communityId, @PathVariable Long eventId, EventViewForm eventViewForm, HttpServletRequest request, Model model){
		
		EventSO event = eventService.getEventById(eventId);
		
		
		UserSO user = getUser();
		if(user == null){
			return "redirect:";
		}
		CommunityMemberSO communityMemberSO = communityService.getCommunityMemberByCommunityIdAndUserId(communityId, user.getId());
		EventAttenderSO eventAttender = eventService.getEventAttenderByEventIdAndUserId(eventId, user.getId());
		EventSO moderatedEvent = eventService.getModeratedEventByEventIdAndUserId(eventId, user.getId());
		eventViewForm.setCommunityMember(communityMemberSO);
		eventViewForm.setModeratedEvent(moderatedEvent);
		eventViewForm.setEvent(event);
		eventViewForm.setEventAttender(eventAttender);
		eventViewForm.setWallElementsFromEvent();
		eventViewForm.setUser(user);
		// Find User Tags
		List<UserTagSO> userTags = tagService.getUserTagsByUser(user);
		eventViewForm.setUserTags(userTags);
		// Find all Events of User
		List<EventSO> eventListofUser = eventService.getEventsByUser(user);
		// Find Events From User Tags 
		ArrayList<Object> eventList = new ArrayList<Object>();
		eventViewForm.setEventList(eventList);
		for(int i=0; i<userTags.size();i++){
			eventList.addAll(eventService.getEventsByTag(userTags.get(i)));
			}
		eventListofUser.add(eventService.getEventById(eventId));
		// Find Events of Community
		ArrayList<Object> eventListofCommunity = new  ArrayList<Object>();
		eventListofCommunity.addAll(communityService.getCommunityById(communityId).getEvents());
		eventViewForm.setEventListofCommunity(eventListofCommunity);
		// Find Events of Community according User Tags
		
		ArrayList<Object> eventListofRecommendation = new  ArrayList<Object>();
		for(int i=0;i<eventListofCommunity.size();i++)
		{
			if(eventList.contains(eventListofCommunity.get(i)))
			{
				eventListofRecommendation.add(eventListofCommunity.get(i));
			}
		}
		eventViewForm.setEventListofRecommendation(eventListofRecommendation);
		
		// Exclude Already Member Events from above found
		for(int i=0; i<eventListofUser.size();i++)
		{
		eventListofRecommendation.remove(eventListofUser.get(i));
		}

		
		return "viewEvent";
	}
	/**
	 * a controller for posting on an event wall
	 * @param communityId
	 * @param eventId
	 * @param eventViewForm
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events/{eventId}/post")
	public String post(@PathVariable Long communityId, @PathVariable Long eventId, EventViewForm eventViewForm, HttpServletRequest request, Model model){
		
		String post = eventViewForm.getPost();
		
		System.out.println(post);
		
//		CommunitySO community = communityService.getCommunityById(communityId);
		UserSO user = getUser();
		
		EventPostSO eventPost;
//		if(community != null && user != null)	
			eventPost = eventService.saveEventPost(eventId, user.getId(), post);
		
		return "redirect:/communities/{communityId}/events/" + eventId;
	}
	/**
	 * a controller for attending an event
	 * @param communityId
	 * @param eventId
	 * @param eventViewForm
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events/{eventId}/attendEvent")
	public String attendEvent(@PathVariable Long communityId, @PathVariable Long eventId, EventViewForm eventViewForm, HttpServletRequest request, Model model){
		
		UserSO user = getUser();
		if(user == null)
			return "redirect:";
		
		eventService.saveEventAttender(eventId, getUser().getId());
		
		return "redirect:/communities/{communityId}/events/" + eventId;
	}
	/**
	 * a controller for unattending an event
	 * @param communityId
	 * @param eventId
	 * @param eventViewForm
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events/{eventId}/unattendEvent")
	public String unattendEvent(@PathVariable Long communityId, @PathVariable Long eventId, EventViewForm eventViewForm, HttpServletRequest request, Model model){
		
		UserSO user = getUser();
		if(user == null)
			return "redirect:";
		
		eventService.deleteEventAttender(eventId, getUser().getId());
		
		return "redirect:/communities/{communityId}/events/" + eventId;
	}
	/**
	 * a method for validating an event
	 * @param eventCreateForm
	 * @param errors
	 */
	private void validateNewEvent(EventCreateForm eventCreateForm, BindingResult errors) {
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "event.name", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startingDay", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startingHour", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "endingDay", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "endingHour", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "event.description", "required.field");
	}
	private void validateEditedEvent(EventUpdateForm eventUpdateForm, BindingResult errors) {
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "event.name", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startingDay", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "startingHour", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "endingDay", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "endingHour", "required.field");
		ValidationUtils.rejectIfEmptyOrWhitespace(errors, "event.description", "required.field");
	}
	/**
	 * a controller for editing an event for a moderator.
	 * @param communityId
	 * @param eventId
	 * @param eventUpdateForm
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events/{eventId}/editEvent")
	public String editEvent(@PathVariable Long communityId, @PathVariable Long eventId, EventUpdateForm eventUpdateForm, BindingResult errors, HttpServletRequest request, Model model){
		
		EventSO event = eventService.getEventById(eventId);
		
		if(event != null){
			eventUpdateForm.setEvent(event);
			List<TagSO> selectedTags = tagService.getTagsByRelatedEventId(eventId);
			moderatorsList = eventService.getModeratorsByEventId(eventId);
			creator = event.getCreator();
			eventUpdateForm.setSelectedTagsFromList(selectedTags);
			DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm");
			String startingDate = df.format(event.getStartingTime());
			String endingDate = df.format(event.getEndingTime());    
			eventUpdateForm.setStartingDay(startingDate.substring(0,10));
			eventUpdateForm.setStartingHour(startingDate.substring(10));
			eventUpdateForm.setEndingDay(endingDate.substring(0,10));
			eventUpdateForm.setEndingHour(endingDate.substring(10));

		}

		return "updateEvent";
	}
	/**
	 * a controller for editing an event with post method
	 * @param communityId
	 * @param eventId
	 * @param eventUpdateForm
	 * @param request
	 * @param model
	 * @return
	 */
	@RequestMapping(value = "/communities/{communityId}/events/{eventId}/updateEvent", method = RequestMethod.POST)
	public String updateEvent(@PathVariable Long communityId, @PathVariable Long eventId, EventUpdateForm eventUpdateForm, BindingResult errors, HttpServletRequest request, Model model){
		
		validateEditedEvent(eventUpdateForm, errors);
		if(errors.hasErrors()){
			return editEvent(communityId, eventId, eventUpdateForm, errors, request, model);
		}
		eventUpdateForm.setStartAndEndDates();
		EventSO event = eventUpdateForm.getEvent();
		
		for(UserSO so : moderatorsList)
		{
			event.getModerators().add(so);
		}
		
		System.out.println("----------------------------------  " + event.getId());;

		event.setId(eventId);
		event.setCreator(creator);
		event.setActivityType(ActivityType.NONE);
		event.setCommunity(communityService.getCommunityById(communityId));
		eventService.updateEvent(event);
		List<String> selectedTags = eventUpdateForm.getSelectedTagsAsList();
		
		tagService.saveEventTags(event,selectedTags);	
				
		return "redirect:/communities/" + communityId + "/events/" + eventId + "/editEvent";
	}
	
}
